package com.qianbao.finance.sync.modules.elasticsearch.websocket.server;

import com.qianbao.finance.sync.common.utils.SpringContextUtils;
import org.apache.log4j.Logger;
import org.jboss.netty.channel.ChannelHandlerContext;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;

/**
 * 单实例管理器：管理Session、ChatRoom、定时心跳、定时清理、当前sessionId、共用的ExecutorService
 * 
 * @author WangYuan
 * @date 2016年7月12日下午3:18:20
 */
public class ShareBean {

    private static final Logger logger = Logger.getLogger(ShareBean.class);
    /**
     * 单实例
     */
    private static final ShareBean instance = new ShareBean();

    private static ShareConfig shareConfig = (ShareConfig) SpringContextUtils.getBean("shareConfig");
    /**
     * 聊天室名字和聊天室实例映射表
     */
    private ConcurrentHashMap<String, ChatRoom> chatRooms;

    /**
     * 线程池
     */
    private ExecutorService chatRoomExecutorService;

    private int chatRoomWorkerThreadId = 0;

    private int getNextChatRoomWorkerThreadId() {
        return chatRoomWorkerThreadId++;
    }

    /**
     * 定时清理资源
     */
    private Thread clearResourceTask = new Thread() {
        @Override
        public void run() {
            while (shareConfig.isRunning()) {
                logger.info("清理资源线程,isRunning: " + shareConfig.isRunning());
                Set<String> ks = chatRooms.keySet();
                for (String key : ks) {
                    ChatRoom chatRoom = chatRooms.get(key);
                    chatRoom.cleanTimeoutSession();
                }
                try {
                    Thread.sleep(shareConfig.getConnClearPeriod());
                } catch (Exception e) {
                    logger.error("", e);
                }
            }
        }
    };

    /**
     * 启动
     */
    public void doStart() {
        this.chatRooms = new ConcurrentHashMap<>(20, 0.75f, 2);
        this.clearResourceTask.start();
        this.chatRoomExecutorService =
                Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors(),
                        new ThreadFactory() {
                            @Override
                            public Thread newThread(Runnable runnable) {
                                Thread thread = new Thread(runnable);
                                thread.setName("聊天室发送线程池-" + getNextChatRoomWorkerThreadId());
                                return thread;
                            }
                        });

    }

    /**
     * 停止
     */
    public void doStop() {

    }

    /**
     * 
     * 
     * @param channelHandlerContext
     */
    public void closeChannelHandlerContext(ChannelHandlerContext channelHandlerContext) {
        Set<String> ks = chatRooms.keySet();
        Set<Integer> clear = new HashSet<>();
        int hashCode = channelHandlerContext.hashCode();
        for (String key : ks) {
            if (!clear.contains(hashCode)) {
                try {
                    channelHandlerContext.getChannel().disconnect();
                } catch (Exception e) {
                    logger.error("closeChannelHandlerContext ", e);
                }
                try {
                    channelHandlerContext.getChannel().close();
                } catch (Exception e) {
                    logger.error("closeChannelHandlerContext ", e);
                }
                clear.add(hashCode);
            }
            chatRooms.get(key).removeChannelHandlerContext(channelHandlerContext);
        }
    }

    /**
     * 生成html格式的房间、会话统计信息
     * 
     * @return
     */
    public String generateChatRoomInfo() {
        StringBuffer info = new StringBuffer();
        info.append("<pre>Room Count: ").append(chatRooms.size()).append("\n");
        Set<String> ks = chatRooms.keySet();
        for (String key : ks) {
            info.append(key).append(" Session Count: ")
                    .append(chatRooms.get(key).getConnectionCount()).append("\n");
        }
        info.append("\n");
        info.append("</pre>");
        return info.toString();
    }

    private ShareBean() {

    }

    public static ShareBean getInstance() {
        return instance;
    }

    public ConcurrentHashMap<String, ChatRoom> getChatRoom() {
        return chatRooms;
    }

    public ExecutorService getChatRoomExecutorService() {
        return chatRoomExecutorService;
    }

}
